module lpuart_top(
input             pclk,
input             presetn,
input             psel,
input             penable,
input             pwrite,
input      [7:0]  paddr,
input      [31:0] pwdata,
output     [31:0] prdata,

input             uart_clk,    
input             uart_rst_n,

input             dma_tx_ack,
input             dma_rx_ack,
output            dma_tx_req,
output            dma_rx_req,

output            lpuart_irq,
output            lp_wake_up_irq,

output            tx_pin_oe,
input             tx_pin_in,
output            tx_pin_out,
output            rx_pin_oe,
input             rx_pin_in,
output            rx_pin_out,
output            rts_n,
output            rts_oe,
input             cts_n
);


wire txinv;
wire rxinv;
wire swap_tx_rx;

wire fifo_en;
wire rxfnf;
wire rxne;
wire sync_fifo_en;
wire sync_rxfnf;
wire sync_rxne;
wire sync_rts_en;

wire tx_out_en;
wire tx_out;
wire rxd_sync;

wire tx_finish;
wire sync_tx_finish;
wire tx_idle;

lpuart_pin_proc u0_lpuart_pin_proc(
  .uart_clk    (uart_clk),
  .uart_rst_n  (uart_rst_n),

  .hdsel       (hdsel),
  .txinv       (txinv),
  .rxinv       (rxinv),
  .swap_tx_rx  (swap_tx_rx),

  .fifo_en     (sync_fifo_en),
  .rxfnf       (sync_rxfnf),
  .rxne        (rxne),
  .rts_en      (sync_rts_en),

  .tx_out_en   (tx_out_en),
  .tx_out      (tx_out),
  .rxd_sync    (rxd_sync),

  .rx_pin_in   (rx_pin_in),
  .tx_pin_in   (tx_pin_in),
  .rx_pin_out  (rx_pin_out),
  .tx_pin_out  (tx_pin_out),
  .tx_pin_oe   (tx_pin_oe),
  .rts_oe      (rts_oe),
  .rts_n       (rts_n)
);


// lpuart_apb_biu <=> lpuart_regfile
wire wr_en, rd_en;
wire [5:0]  reg_addr;
wire [31:0] ipwdata;
wire [31:0] iprdata;

lpuart_apb_biu u0_lpuart_apb_biu(
  .pclk      (pclk),
  .presetn   (presetn),
  .psel      (psel),
  .penable   (penable),
  .pwrite    (pwrite),
  .paddr     (paddr),
  .pwdata    (pwdata),
  .prdata    (prdata),
  
  .iprdata   (iprdata),
  .wr_en     (wr_en),
  .rd_en     (rd_en),
  .reg_addr  (reg_addr),
  .ipwdata   (ipwdata)
);

// lpuart_fifo <=> lpuart_regfile
wire          tx_push;
wire [9-1:0]  tx_push_data;
wire          tx_wfull;
wire          tx_wone_eighth_thr;
wire          tx_wone_quarter_thr;
wire          tx_wone_half_thr;
wire          tx_wthree_quarter_thr;
wire          tx_wseven_eighth_thr;
wire          rx_pop;
wire [12-1:0] rx_pop_data;
wire          rx_rempty;
wire          rx_rone_eighth_thr;
wire          rx_rone_quarter_thr;
wire          rx_rone_half_thr;
wire          rx_rthree_quarter_thr;
wire          rx_rseven_eighth_thr;

// lpuart_fifo <=> lpuart_tx
wire          tx_pop;
wire [9-1:0]  tx_pop_data;
wire          tx_rempty;

// lpuart_fifo <=> lpuart_rx
wire          rx_push;
wire [12-1:0] rx_push_data;
wire          rx_wfull;



// lpuart_regfile <=> lpuart_sync
wire  [3:0]   clock_psc;
wire  [19:0]  baud_rate;
wire          sync_rx_busy;
wire          sync_cts_n;

// lpuart_rx/tx <=> lpuart_regfile
wire          stop_1bit;
wire          stop_2bit;
wire          frame_7bit;
wire          frame_8bit;
wire          frame_9bit;
wire          pce;
wire          ps;

// lpuart_rx <=> lpuart_regfile
wire          rx_en;
wire          rts_en;
wire          mmrq;
wire    [7:0] wake_addr;
wire          wake_addrm7;
wire          wake_method;
wire          uesm;

wire          overrun_err;

wire           rwu;
wire           rx_busy;
wire           rx_finish;
wire    [11:0] rx_data;
wire    [11:0] sync_rx_data;

// lpuart_tx <=> lpuart_regfile
wire       tx_start;
wire       tx_en;
wire [8:0] tx_data_reg;
wire       txfrq;
wire       sbkrq;
wire       cts_en;
wire       clr_cts;
wire       msbfirst;

//lpuart_hdw_top(
//.cts(cts),
//.rts_oe(rts_oe),
//.rts(rts),
//.de(de),
//.dedt(cr1_dedt_r),
//.deat(cr1_deat_r),
//.brr_dat(baud_rate),
//.pclk(pclk),
//.presetn(presetn),
//.uart_clk(uart_clk),
//.uart_rst_n(uart_rst_n)
//);


lpuart_regfile u0_lpuart_regfile(
  .pclk                   (pclk),
  .presetn                (presetn),

  .wr_en                  (wr_en),
  .rd_en                  (rd_en),
  .reg_addr               (reg_addr),
  .ipwdata                (ipwdata),
  .iprdata                (iprdata),

  // pin proc
  .rxfnf                  (rxfnf),

  // dma
  .dma_tx_ack             (dma_tx_ack),
  .dma_rx_ack             (dma_rx_ack),
  .dma_tx_req             (dma_tx_req),
  .dma_rx_req             (dma_rx_req),

  // lpuart_fifo
  .tx_push                (tx_push),
  .tx_push_data           (tx_push_data),
  .tx_wfull               (tx_wfull),
  .tx_wone_eighth_thr     (tx_wone_eighth_thr),
  .tx_wone_quarter_thr    (tx_wone_quarter_thr),
  .tx_wone_half_thr       (tx_wone_half_thr),
  .tx_wthree_quarter_thr  (tx_wthree_quarter_thr),
  .tx_wseven_eighth_thr   (tx_wseven_eighth_thr),
  .rx_pop                 (rx_pop),
  .rx_pop_data            (rx_pop_data),
  .rx_rempty              (rx_rempty),
  .rx_rone_eighth_thr     (rx_rone_eighth_thr),
  .rx_rone_quarter_thr    (rx_rone_quarter_thr),
  .rx_rone_half_thr       (rx_rone_half_thr),
  .rx_rthree_quarter_thr  (rx_rthree_quarter_thr),
  .rx_rseven_eighth_thr   (rx_rseven_eighth_thr),

  // lpuart_bclk_gen
  .clock_psc              (clock_psc),
  .baud_rate              (baud_rate),
  .ue                     (ue),

  // lpuart_rx & lpuart_tx
  .stop_1bit        (stop_1bit),
  .stop_2bit        (stop_2bit),
  .frame_7bit       (frame_7bit),
  .frame_8bit       (frame_8bit),
  .frame_9bit       (frame_9bit),
  .pce              (pce),
  .ps               (ps),
  .hdsel            (hdsel),
  .msbfirst         (msbfirst),
  .fifo_en          (fifo_en),

  // lpuart_rx
  .rwu              (rwu),
  .rx_busy          (sync_rx_busy),
  .rx_finish        (sync_rx_finish),
  .rx_data          (sync_rx_data),

  .rx_en            (rx_en),
  .rts_en           (rts_en),
  .mmrq             (mmrq),
  .wake_addrm7      (wake_addrm7),
  .wake_addr        (wake_addr),
  .wake_method      (wake_method),
  .uesm             (uesm),

  // lpuart_tx
  .tx_start         (tx_start),
  .tx_en            (tx_en),
  .tx_data_reg      (tx_data_reg),
  .txfrq            (txfrq),
  .sbkrq            (sbkrq),
  .cts_en           (cts_en),
  .clr_cts          (clr_cts),
  .tx_finish        (sync_tx_finish),

  .cts_n            (sync_cts_n),
  .txinv            (txinv),
  .rxinv            (rxinv),
  .swap_tx_rx       (swap_tx_rx)
);

lpuart_fifo u0_lpuart_fifo(
  .pclk                  (pclk),
  .presetn               (presetn),
  .uart_clk              (uart_clk),
  .uart_rst_n            (uart_rst_n),

  .tx_push               (tx_push),
  .tx_push_data          (tx_push_data),
  .tx_wfull              (tx_wfull),
  .tx_wone_eighth_thr    (tx_wone_eighth_thr),
  .tx_wone_quarter_thr   (tx_wone_quarter_thr),
  .tx_wone_half_thr      (tx_wone_half_thr),
  .tx_wthree_quarter_thr (tx_wthree_quarter_thr),
  .tx_wseven_eighth_thr  (tx_wseven_eighth_thr),
  .tx_pop                (tx_pop),
  .tx_pop_data           (tx_pop_data),
  .tx_rempty             (tx_rempty),

  .rx_pop                (rx_pop),
  .rx_pop_data           (rx_pop_data),
  .rx_rempty             (rx_rempty),
  .rx_rone_eighth_thr    (rx_rone_eighth_thr),
  .rx_rone_quarter_thr   (rx_rone_quarter_thr),
  .rx_rone_half_thr      (rx_rone_half_thr),
  .rx_rthree_quarter_thr (rx_rthree_quarter_thr),
  .rx_rseven_eighth_thr  (rx_rseven_eighth_thr),
  .rx_wfull              (rx_wfull),
  .rx_push               (rx_push),
  .rx_push_data          (rx_push_data)
);

wire  sync_stop_1bit;
wire  sync_stop_2bit;
wire  sync_frame_7bit;
wire  sync_frame_8bit;
wire  sync_frame_9bit;
wire  sync_pce;
wire  sync_ps;
wire  sync_msbfirst;

wire       sync_rx_en;
wire       sync_rxfrq;
wire       sync_mmrq;
wire       sync_wake_addrm7;
wire       sync_wake_method;
wire       sync_uesm;

wire       sync_tx_start;
wire       sync_tx_en;
wire [8:0] sync_tx_data_reg;
wire       sync_txfrq;
wire       sync_sbkrq;
wire       sync_cts_en;
wire       sync_clr_cts;


lpuart_sync u0_lpuart_sync(
  // pclk
  .pclk              (pclk),
  .presetn           (presetn),
  .uart_clk          (uart_clk),
  .uart_rst_n        (uart_rst_n),

  // pclk -> uart_clk
  .ue                (ue),

  .stop_1bit         (stop_1bit),
  .stop_2bit         (stop_2bit),
  .frame_7bit        (frame_7bit),
  .frame_8bit        (frame_8bit),
  .frame_9bit        (frame_9bit),
  .pce               (pce),
  .ps                (ps),
  .msbfirst          (msbfirst),
  .fifo_en           (fifo_en),

  .rx_en             (rx_en),
  .rts_en            (rts_en),
  .mmrq              (mmrq),
  .wake_addrm7       (wake_addrm7),
  .wake_method       (wake_method),
  .uesm              (uesm),

  .tx_start          (tx_start),
  .tx_en             (tx_en),
  .tx_data_reg       (tx_data_reg),
  .txfrq             (txfrq),
  .sbkrq             (sbkrq),
  .cts_en            (cts_en),
  .clr_cts           (clr_cts),

  .rxfnf             (rxfnf),

  // uart_clk -> pclk
  .uart_lp_req       (uart_lp_req),
  .tx_idle           (tx_idle),
  .tx_finish         (tx_finish),
  .rx_busy           (rx_busy),
  .rx_finish         (rx_finish),
  .rx_pop_ack        (rx_pop_ack),
  .rx_data           (rx_data),
  .cts_n             (cts_n),

  // pclk -> uart_clk
  .sync_ue           (sync_ue),

  .sync_stop_1bit    (sync_stop_1bit),
  .sync_stop_2bit    (sync_stop_2bit),
  .sync_frame_7bit   (sync_frame_7bit),
  .sync_frame_8bit   (sync_frame_8bit),
  .sync_frame_9bit   (sync_frame_9bit),
  .sync_pce          (sync_pce),
  .sync_ps           (sync_ps),
  .sync_msbfirst     (sync_msbfirst),

  .sync_rx_en        (sync_rx_en),
  .sync_rts_en       (sync_rts_en),
  .sync_rxfrq        (sync_rxfrq),
  .sync_mmrq         (sync_mmrq),
  .sync_wake_addrm7  (sync_wake_addrm7),
  .sync_wake_method  (sync_wake_method),
  .sync_uesm         (sync_uesm),

  .sync_tx_start     (sync_tx_start),
  .sync_tx_en        (sync_tx_en),
  .sync_tx_data_reg  (sync_tx_data_reg),
  .sync_txfrq        (sync_txfrq),
  .sync_sbkrq        (sync_sbkrq),
  .sync_cts_en       (sync_cts_en),
  .sync_clr_cts      (sync_clr_cts),

  .sync_fifo_en      (sync_fifo_en),
  .sync_rxfnf        (sync_rxfnf),

  // uart_clk -> pclk
  .sync_uart_lp_req  (sync_uart_lp_req),
  .sync_tx_finish    (sync_tx_finish),
  .sync_rx_busy      (sync_rx_busy),
  .sync_rx_finish    (sync_rx_finish),
  .sync_rx_data      (sync_rx_data),
  .sync_cts_n        (sync_cts_n)
);


// lpuart_bclk_gen <=> rx/tx
wire baud_clk;
wire baud_clk_offset;
wire baud_clk_start;

lpuart_bclk_gen u0_lpuart_bclk_gen(
  .uart_clk       (uart_clk),    
  .uart_rst_n     (uart_rst_n), 
  
  .clock_psc      (clock_psc),
  .baud_rate      (baud_rate),
  .stop_bclk      (~sync_ue),
  .baud_clk_start (baud_clk_start),

  // rx/tx
  .baud_clk       (baud_clk),
  .baud_clk_offset(baud_clk_offset)
);


lpuart_rx u0_lpuart_rx(
  .uart_clk        (uart_clk),
  .uart_rst_n      (uart_rst_n),

  .baud_clk        (baud_clk),
  .baud_clk_offset (baud_clk_offset),

  .rxd_sync        (rxd_sync),

  .stop_1bit       (sync_stop_1bit),
  .stop_2bit       (sync_stop_2bit),
  .frame_7bit      (sync_frame_7bit),
  .frame_8bit      (sync_frame_8bit),
  .frame_9bit      (sync_frame_9bit),
  .pce             (sync_pce),
  .ps              (sync_ps),
  .msbfirst        (sync_msbfirst),
  .fifo_en         (fifo_en),

  .rx_en           (sync_rx_en),
  .mmrq            (sync_mmrq),
  .wake_addr       (wake_addr),
  .wake_addrm7     (sync_wake_addrm7),
  .wake_method     (sync_wake_method),
  .uesm            (sync_uesm),

  .baud_clk_start  (baud_clk_start),

  .rx_push         (rx_push),
  .rx_push_data    (rx_push_data),
  .rx_wfull        (rx_wfull),

  .lp_wake_up_irq  (lp_wake_up_irq),
  .rxne            (rxne),
  .rwu             (rwu),
  .rx_busy         (rx_busy),
  .rx_finish       (rx_finish),
  .rx_data         (rx_data)
);

lpuart_tx u0_lpuart_tx(
  .uart_clk        (uart_clk),
  .uart_rst_n      (uart_rst_n),

  .baud_clk        (baud_clk),

  .stop_1bit       (sync_stop_1bit),
  .stop_2bit       (sync_stop_2bit),
  .frame_7bit      (sync_frame_7bit),
  .frame_8bit      (sync_frame_8bit),
  .frame_9bit      (sync_frame_9bit),
  .pce             (sync_pce),
  .ps              (sync_ps),
  .msbfirst        (sync_msbfirst),
  .fifo_en         (fifo_en),

  .tx_start        (sync_tx_start),
  .tx_en           (sync_tx_en),
  .tx_data_reg     (sync_tx_data_reg),
  .txfrq           (sync_txfrq),
  .sbkrq           (sync_sbkrq),
  .cts_en          (sync_cts_en),
  .cts_n           (cts_n),

  .tx_pop          (tx_pop),
  .tx_pop_data     (tx_pop_data),
  .tx_rempty       (tx_rempty),

  .tx_idle         (tx_idle),
  .tx_finish       (tx_finish),
  .tx_out_en       (tx_out_en),
  .tx_out          (tx_out)
);

endmodule
